﻿
// 2023/11/14: 首个记录。基于v1 2023/11/1版本，增加分类置信度和描述信息字段，distance改为可选字段
// 2025/4/18: 增加仪表盘标识大类

#ifndef IMAGE_LABEL_SAMPLE_V2_H
#define IMAGE_LABEL_SAMPLE_V2_H

#include "spadas.h"

namespace image_label_sample_v2
{
	using namespace spadas;

	enum LabelClass
	{
		LBC_Unknown = 0, // 未知

		LBC_GeneralCar = 100, // General automobile / 机动车大类
		LBC_Car = 101, // 轿车
		LBC_Bus = 102,// 大巴
		LBC_Midibus = 103,// 小巴
		LBC_Truck = 104, // 货车
		LBC_Van = 105, // 面包车
		LBC_Semitrailer = 106, // 货柜车
		LBC_Trailer = 107, // 拖车
		LBC_SUV = 108, // SUV
		LBC_TinyCar = 109, // 微型车

		LBC_GeneralMinority = 200, // General vulnerable road user / 弱势参与者大类
		LBC_Pedestrian = 201, // Pedestrian / 行人
		LBC_Bicycle = 202, // 自行车
		LBC_Tricycle = 203, // 三轮车
		LBC_Motorbike = 204, // 摩托车
		LBC_Wheelchair = 205, // 轮椅
		LBC_Animal = 206, // 动物

		LBC_GeneralStatic = 300, // General static object / 静态目标大类
		LBC_ZebraCrossing = 301, // 斑马线
		LBC_TrafficLight = 302, // 交通灯
		LBC_TrafficSign = 303, // 交通信号
		LBC_ParkingSlot = 304, // 车位
		LBC_Cone = 305, // 锥形路障
		LBC_ManholeCover = 306, // 井盖
		LBC_Patch = 307, // 路面补丁
		LBC_Gantry = 308, // 龙门架
		LBC_Pole = 309, // 竖杆
		LBC_Tree = 310, // 树木
		LBC_Vegetation = 311, // 灌木
		LBC_Building = 312, // 建筑物

		LBC_Dashboard = 1000, // Dashboard signal / 仪表盘标识大类
		LBC_Airbag = 1001, // 安全气囊
		LBC_ABS = 1002, // 防抱死制动
		LBC_BrakeSystemFailure = 1003, // 刹车系统故障
		LBC_ChargingSystemFailure = 1004, // 充电系统故障
		LBC_CentralWarningLamp = 1005, // 中央警告灯
		LBC_CoolingSystemFailure = 1006, // 冷却系统故障
		LBC_DoorsOpen = 1007, // 车门未关
		LBC_ElectronicPowerSteering = 1008, // 转向助力
		LBC_ElectronicStability = 1009, // 电子稳定性(ESC)
		LBC_EnginePreheating = 1010, // 发动机预热
		LBC_FrontFogLight = 1011, // 前雾灯
		LBC_LaneDepartureWarning = 1012, // 车道偏离预警
		LBC_LowBeam = 1013, // 近光灯
		LBC_LowEngineOilWarning = 1014, // 低燃油警告
		LBC_SeatBelt = 1015, // 安全带提醒
		LBC_SideLamp = 1016, // 示廓灯
		LBC_TyrePressureMonitoring = 1017, // 胎压异常
		LBC_WasherFluid = 1018, // 玻璃水不足
	};

	struct ImageLabel
	{
		UInt id; // 标签ID
		LabelClass clas; // 标签类型
		OptionalDouble classConfidence; // [%] Classification confidence / 分类置信度
		OptionalDouble distance; // [m] Average distance between the label's pixels to the camera (along x axis of camera coordinate system) / 标签距摄像头的平均距离（沿摄像头x轴方向）
		Point2D topLeft; // [pix] Coordination of the top left point of label's border / 标签矩形框的左上角坐标
		Point2D bottomRight; // [pix] Coordination of the bottom right point of label's border / 标签矩形框的右下角坐标
		String description; // 描述信息
	};

	struct ImageLabelSample
	{
		FullTimestamp timestamp; // 时间戳
		UInt channel; // Corresponding video channel / 对应的视频通道
		Size2D imageSize; // [pix] 图像尺寸
		Array<ImageLabel> labels; // List of labels / 标签列表

		ImageLabelSample()
		{
			channel = UINF;
		}

		static String getProtocolName(UInt channel)
		{
			if (channel == UINF) return "image-label-sample-v2";
			else return (String)"image-label-sample-v2@" + channel;
		}

		static Bool supportInterpolation()
		{
			return FALSE;
		}

		SessionGeneralSample toGeneralSample()
		{
			SessionGeneralSample sample;

			sample.timestamp = timestamp;
			sample.values = Array<GeneralElement>(8 + labels.size() * 16);
			GeneralElement *data = sample.values.data();

			data[0] = (Double)channel;
			data[1] = imageSize.width;
			data[2] = imageSize.height;
			data[3] = (Double)labels.size();
			for (UInt i = 0; i < labels.size(); i++)
			{
				ImageLabel& src = labels[i];
				data[16 * i + 8] = (Double)(UInt)src.clas;
				data[16 * i + 9] = (Double)src.id;
				data[16 * i + 10] = src.distance;
				data[16 * i + 11] = src.topLeft.u;
				data[16 * i + 12] = src.topLeft.v;
				data[16 * i + 13] = src.bottomRight.u;
				data[16 * i + 14] = src.bottomRight.v;
				data[16 * i + 15] = src.classConfidence;
				data[16 * i + 16] = src.description;
			}

			sample.significantCount = sample.values.size();
			return sample;
		}

		Bool fromGeneralSample(String protocol, SessionGeneralSample sample)
		{
			// TODO
			return FALSE;
		}

		static ImageLabelSample interpolate(ImageLabelSample& s1, Double w1, ImageLabelSample& s2, Double w2, FullTimestamp timestamp)
		{
			return ImageLabelSample();
		}
	};
}

#endif